const fs = require('fs'),
      url = require('url'),
      http = require('http'),
      path = require('path'),
      mime = require('mime'),
      config = require('./config'),
      handlebars = require('handlebars'),
      { promisify,inspect } = require('util');

const stat = promisify(fs.stat),
      readdir = promisify(fs.readdir);

const list = () => {
    const tmpl = fs.readFileSync(path.resolve(__dirname,'tmp.html'),'utf8');
    return handlebars.compile(tmpl);
}

class Server {
    constructor(argv) {
        this.list = list(); 
        this.config = Object.assign({},config,argv);
    }
    start() {
        const server = http.createServer();
        server.on('request', this.request.bind(this));
        server.listen(this.config.port, () => {
            console.log('server started at ' + this.config.host + ':' + this.config.port);
        })
    }
    async request(req,res) {
        const { pathname } = url.parse(req.url),
              filepath = path.join(this.config.root, 'public', pathname);
        if(pathname == '/favicon.ico') return this.sendError(req,res);
        try {
            let statObj = await stat(filepath);
            if(statObj.isDirectory()) {
                let files = await readdir(filepath);
                files = files.map(file => ({
                    name: file,
                    url: path.join(pathname,file)
                }));
                let html = this.list({
                    title: pathname,
                    files
                });
                res.setHeader('Content-Type','text/html');
                res.end(html);
            }else {
                this.sendFile(req,res,filepath,statObj);
            }
        } catch (e) {
            console.log(inspect(e));
            this.sendError(req,res)
        }
    }
    sendFile(req,res,filepath,statObj) {
        res.setHeader('Content-Type', mime.getType(filepath));
        fs.createReadStream(filepath).pipe(res);
    }
    sendError(req,res) {
        res.statusCode = 500;
        res.end('there is something wrong in the server! please try later!')
    }
};

/* const server = new Server();
server.start(); */

module.exports = Server;

